package com.loong.android.views.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewParent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.loong.android.R;
import com.loong.android.utils.CharSequenceUtils;
import com.loong.android.views.LonView;
import com.loong.android.views.data.BgLinearGradient;
import com.loong.android.views.data.BgRadialGradient;

public class ViewImpl {

    protected final static int WRAP_CONTENT = -2;
    protected final static int MATCH_PARENT = -1;

    protected final View view;

    //背景图片的bitmap
    protected Bitmap mBackgroundBitmap;

    protected int mBackgroundColor = Color.TRANSPARENT;
    protected int mBorderWidth = 0;
    protected int mBorderColor = 0;
    protected int mBorderType = LonView.BORDER_TYPE_SOLID;
    //圆角
    protected float[] mCornerRadii = null;

    protected float mShadowRadius = 0;
    protected float mShadowDx = 0;
    protected float mShadowDy = 0;
    protected int mShadowColor = Color.TRANSPARENT;
    protected boolean mRippleEffect = false;

    protected Integer mLayoutWidth = null;
    protected Integer mLayoutHeight = null;
    protected Integer mPadding = null;
    protected Integer mPaddingLeft = null;
    protected Integer mPaddingTop = null;
    protected Integer mPaddingRight = null;
    protected Integer mPaddingBottom = null;
    protected Integer mLayoutMargin = null;
    protected Integer mLayoutMarginLeft = null;
    protected Integer mLayoutMarginRight = null;
    protected Integer mLayoutMarginTop = null;
    protected Integer mLayoutMarginBottom = null;

    protected float mLinearGradientX0 = 0;
    protected float mLinearGradientY0 = 0;
    protected float mLinearGradientX1 = 1;
    protected float mLinearGradientY1 = 1;
    protected int mLinearGradientMode = 0;
    protected int[] mLinearGradientColors = null;
    protected float[] mLinearGradientPositions = null;
    protected Integer mLinearGradientColorStart = null;
    protected Integer mLinearGradientColorEnd = null;

    protected float mRadialGradientCenterX = 0.5f;
    protected float mRadialGradientCenterY = 0.5f;
    protected float mRadialGradientRadius = -2;
    protected int mRadialGradientMode = 0;
    protected int[] mRadialGradientColors = null;
    protected float[] mRadialGradientPositions = null;
    protected Integer mRadialGradientColorCenter = null;
    protected Integer mRadialGradientColorEdge = null;

    protected BgLinearGradient bgLinearGradient = null;
    protected BgRadialGradient bgRadialGradient = null;

    public ViewImpl(View view) {
        this.view = view;
    }

    public void initView(Context context, AttributeSet attrs) {
        if (context == null) return;
        if (attrs != null) {
            @SuppressLint("CustomViewStyleable")
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.View);
            if(ta.hasValue(R.styleable.View_android_layout_width)) {
                mLayoutWidth = ta.getLayoutDimension(R.styleable.View_android_layout_width, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_height)) {
                mLayoutHeight = ta.getLayoutDimension(R.styleable.View_android_layout_height, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_margin)) {
                mLayoutMargin = ta.getDimensionPixelSize(R.styleable.View_android_layout_margin, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginLeft)) {
                mLayoutMarginLeft = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginLeft, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginStart)) {
                mLayoutMarginLeft = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginStart, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginTop)) {
                mLayoutMarginTop = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginTop, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginRight)) {
                mLayoutMarginRight = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginRight, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginEnd)) {
                mLayoutMarginRight = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginEnd, 0);
            }
            if(ta.hasValue(R.styleable.View_android_layout_marginBottom)) {
                mLayoutMarginBottom = ta.getDimensionPixelSize(R.styleable.View_android_layout_marginBottom, 0);
            }
            if(ta.hasValue(R.styleable.View_android_padding)) {
                mPadding = ta.getDimensionPixelSize(R.styleable.View_android_padding, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingLeft)) {
                mPaddingLeft = ta.getDimensionPixelSize(R.styleable.View_android_paddingLeft, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingStart)) {
                mPaddingLeft = ta.getDimensionPixelSize(R.styleable.View_android_paddingStart, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingTop)) {
                mPaddingTop = ta.getDimensionPixelSize(R.styleable.View_android_paddingTop, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingRight)) {
                mPaddingRight = ta.getDimensionPixelSize(R.styleable.View_android_paddingRight, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingEnd)) {
                mPaddingRight = ta.getDimensionPixelSize(R.styleable.View_android_paddingEnd, 0);
            }
            if(ta.hasValue(R.styleable.View_android_paddingBottom)) {
                mPaddingBottom = ta.getDimensionPixelSize(R.styleable.View_android_paddingBottom, 0);
            }

            mBackgroundColor = ta.getColor(R.styleable.View_backgroundColor, mBackgroundColor);
            int backgroundResId = ta.getResourceId(R.styleable.View_android_background, -1);
            if (backgroundResId != -1) {
                mBackgroundBitmap = BitmapUtils.fromResource(context, backgroundResId);
            }
            mBorderWidth = ta.getDimensionPixelSize(R.styleable.View_borderWidth, mBorderWidth);
            mBorderColor = ta.getColor(R.styleable.View_borderColor, Color.TRANSPARENT);
            mBorderType = ta.getInt(R.styleable.View_borderType, mBorderType);

            mShadowRadius = ta.getDimension(R.styleable.View_shadowRadius, mShadowRadius);
            mShadowDx = ta.getDimension(R.styleable.View_shadowDx, mShadowDx);
            mShadowDy = ta.getDimension(R.styleable.View_shadowDy, mShadowDy);
            mShadowColor = ta.getColor(R.styleable.View_shadowColor, mShadowColor);

            mRippleEffect = ta.getBoolean(R.styleable.View_rippleEffect, mRippleEffect);

            int cornerTopLeft = 0, cornerTopRight = 0, cornerBottomLeft = 0, cornerBottomRight = 0;
            if(mCornerRadii != null) {
                cornerTopLeft = (int) mCornerRadii[0];
                cornerTopRight = (int) mCornerRadii[2];
                cornerBottomRight = (int) mCornerRadii[4];
                cornerBottomLeft = (int) mCornerRadii[6];
            }
            if (ta.hasValue(R.styleable.View_corner)) {
                cornerTopLeft = ta.getDimensionPixelSize(R.styleable.View_corner, 0);
                cornerTopRight = cornerTopLeft;
                cornerBottomRight = cornerTopLeft;
                cornerBottomLeft = cornerTopLeft;
            }
            if (ta.hasValue(R.styleable.View_cornerTopLeft)) {
                cornerTopLeft = ta.getDimensionPixelSize(R.styleable.View_cornerTopLeft, 0);
            }
            if (ta.hasValue(R.styleable.View_cornerTopRight)) {
                cornerTopRight = ta.getDimensionPixelSize(R.styleable.View_cornerTopRight, 0);
            }
            if (ta.hasValue(R.styleable.View_cornerBottomRight)) {
                cornerBottomRight = ta.getDimensionPixelSize(R.styleable.View_cornerBottomRight, 0);
            }
            if (ta.hasValue(R.styleable.View_cornerBottomLeft)) {
                cornerBottomLeft = ta.getDimensionPixelSize(R.styleable.View_cornerBottomLeft, 0);
            }
            mCornerRadii = new float[]{
                    cornerTopLeft, cornerTopLeft, cornerTopRight, cornerTopRight,
                    cornerBottomRight, cornerBottomRight, cornerBottomLeft, cornerBottomLeft
            };

            if(ta.hasValue(R.styleable.View_cornerClip)) {
                int cornerCLip = ta.getDimensionPixelSize(R.styleable.View_cornerClip, 0);
                if(cornerCLip > 0) setCornerClip(cornerCLip);
            }

            if (ta.hasValue(R.styleable.View_backgroundLinearGradientX0)) {
                mLinearGradientX0 = ta.getFloat(R.styleable.View_backgroundLinearGradientX0, mLinearGradientX0);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientY0)) {
                mLinearGradientY0 = ta.getFloat(R.styleable.View_backgroundLinearGradientY0, mLinearGradientY0);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientX1)) {
                mLinearGradientX1 = ta.getFloat(R.styleable.View_backgroundLinearGradientX1, mLinearGradientX1);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientY1)) {
                mLinearGradientY1 = ta.getFloat(R.styleable.View_backgroundLinearGradientY1, mLinearGradientY1);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientColorStart)) {
                mLinearGradientColorStart = ta.getColor(R.styleable.View_backgroundLinearGradientColorStart, 0);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientColorEnd)) {
                mLinearGradientColorEnd = ta.getColor(R.styleable.View_backgroundLinearGradientColorEnd, 0);
            }
            if (ta.hasValue(R.styleable.View_backgroundLinearGradientMode)) {
                mLinearGradientMode = ta.getInt(R.styleable.View_backgroundLinearGradientMode, 0);
            }

            resetBgLinearGradient();

            if (ta.hasValue(R.styleable.View_backgroundRadialGradientCenterX)) {
                mRadialGradientCenterX = ta.getFloat(R.styleable.View_backgroundRadialGradientCenterX, mRadialGradientCenterX);
            }
            if (ta.hasValue(R.styleable.View_backgroundRadialGradientCenterY)) {
                mRadialGradientCenterY = ta.getFloat(R.styleable.View_backgroundRadialGradientCenterY, mRadialGradientCenterY);
            }
            if (ta.hasValue(R.styleable.View_backgroundRadialGradientRadius)) {
                mRadialGradientRadius = ta.getFloat(R.styleable.View_backgroundRadialGradientRadius, mRadialGradientRadius);
            }
            if (ta.hasValue(R.styleable.View_backgroundRadialGradientColorCenter)) {
                mRadialGradientColorCenter = ta.getColor(R.styleable.View_backgroundRadialGradientColorCenter, 0);
            }
            if (ta.hasValue(R.styleable.View_backgroundRadialGradientColorEdge)) {
                mRadialGradientColorEdge = ta.getColor(R.styleable.View_backgroundRadialGradientColorEdge, 0);
            }
            if (ta.hasValue(R.styleable.View_backgroundRadialGradientMode)) {
                mRadialGradientMode = ta.getInt(R.styleable.View_backgroundRadialGradientMode, 0);
            }

            resetBgRadialGradient();

            ta.recycle();
        }
    }

    public void resetBgLinearGradient() {
        bgLinearGradient = null;
        if(mLinearGradientColors != null) {
            bgLinearGradient = new BgLinearGradient(mLinearGradientX0, mLinearGradientY0, mLinearGradientX1, mLinearGradientY1,
                    mLinearGradientColors, mLinearGradientPositions, mLinearGradientMode);
        } else if(mLinearGradientColorStart != null || mLinearGradientColorEnd != null) {
            if(mLinearGradientColorStart == null) mLinearGradientColorStart = Color.TRANSPARENT;
            if(mLinearGradientColorEnd == null) mLinearGradientColorEnd = Color.TRANSPARENT;
            bgLinearGradient = new BgLinearGradient(mLinearGradientX0, mLinearGradientY0, mLinearGradientX1, mLinearGradientY1,
                    mLinearGradientColorStart, mLinearGradientColorEnd, mLinearGradientMode);
        }
    }

    public void resetBgRadialGradient(){
        bgRadialGradient = null;
        if(mRadialGradientColors != null) {
            bgRadialGradient = new BgRadialGradient(mRadialGradientCenterX, mRadialGradientCenterY, mRadialGradientRadius,
                    mRadialGradientColors, mRadialGradientPositions, mRadialGradientMode);
        } else if(mRadialGradientColorCenter != null || mRadialGradientColorEdge != null) {
            if(mRadialGradientColorCenter == null) mRadialGradientColorCenter = Color.TRANSPARENT;
            if(mRadialGradientColorEdge == null) mRadialGradientColorEdge = Color.TRANSPARENT;
            bgRadialGradient = new BgRadialGradient(mRadialGradientCenterX, mRadialGradientCenterY, mRadialGradientRadius,
                    mRadialGradientColorCenter, mRadialGradientColorEdge, mRadialGradientMode);
        }
    }

    /**
     * 设置视图的圆角剪切，需要5.0版本以上才有效
     * @param corner 圆角半径
     */
    public void setCornerClip(float corner) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            view.setOutlineProvider(new ViewCornerOutLineProvider(corner));
            view.setClipToOutline(true);
        }
    }

    /**
     * 取消视图的圆角剪切，需要5.0版本以上才有效
     */
    public void cancelCornerClip() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            view.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
            view.setClipToOutline(false);
        }
    }

    /**
     * 取宽度
     */
    public int width() {
        return view.getWidth();
    }

    /**
     * 置宽度
     *
     * @param w 宽度
     */
    public void width(int w) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params == null) params = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
        params.width = w;
        view.setLayoutParams(params);
    }

    /**
     * 取高度
     */
    public int height() {
        return view.getHeight();
    }

    /**
     * 置高度
     *
     * @param h 高度
     */
    public void height(int h) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params == null) params = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
        params.height = h;
        view.setLayoutParams(params);
    }

    /**
     * 设置宽度和高度
     *
     * @param w 宽度
     * @param h 高度
     */
    public void setWidthHeight(int w, int h) {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        if (params == null) params = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
        params.width = w;
        params.height = h;
        view.setLayoutParams(params);
    }

    /**
     * 设置最小宽度
     *
     * @param w 宽度
     */
    public void minWidth(int w) {
        view.setMinimumWidth(w);
    }

    /**
     * 取最小宽度
     */
    public int minWidth() {
        return view.getMinimumWidth();
    }

    /**
     * 设置最小高度
     *
     * @param h 高度
     */
    public void minHeight(int h) {
        view.setMinimumHeight(h);
    }

    /**
     * 取最小高度
     */
    public int minHeight() {
        return view.getMinimumHeight();
    }

    /**
     * 设置描述内容(setContentDescription)
     *
     * @param des 描述
     */
    public void description(String des) {
        view.setContentDescription(des);
    }

    /**
     * 取描述内容(ContentDescription)
     */
    public String description() {
        return CharSequenceUtils.getText(view.getContentDescription());
    }

    /**
     * 置标签数据
     *
     * @param t 数据
     */
    public void tag(Object t) {
        view.setTag(t);
    }

    /**
     * 置标签数据
     *
     * @param key 键名
     * @param t   数据
     */
    public void tag(int key, Object t) {
        view.setTag(key, t);
    }

    /**
     * 取标签数据
     */
    public Object tag() {
        return view.getTag();
    }

    /**
     * 取标签数据
     *
     * @param key 键名
     */
    public Object tag(int key) {
        return view.getTag(key);
    }

    /**
     * 设置透明度
     *
     * @param a 透明度，0-1
     */
    public void alpha(float a) {
        view.setAlpha(a);
    }

    /**
     * 取透明度
     *
     * @return 0-1
     */
    public float alpha() {
        return view.getAlpha();
    }

    /**
     * 置内边距
     *
     * @param left   左内边距
     * @param top    上内边距
     * @param right  右内边距
     * @param bottom 下内边距
     */
    public void padding(int left, int top, int right, int bottom) {
        view.setPadding(left, top, right, bottom);
    }

    /**
     * 置水平方向的内边距
     *
     * @param left  左内边距
     * @param right 上内边距
     */
    public void paddingX(int left, int right) {
        view.setPadding(left, view.getPaddingTop(), right, view.getPaddingBottom());
    }

    /**
     * 置垂直方向的内边距
     *
     * @param top    上内边距
     * @param bottom 下内边距
     */
    public void paddingY(int top, int bottom) {
        view.setPadding(view.getPaddingLeft(), top, view.getPaddingRight(), bottom);
    }

    /**
     * 置左内边距
     *
     * @param val 值
     */
    public void paddingLeft(int val) {
        view.setPadding(val, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
    }

    /**
     * 取左内边距
     */
    public int paddingLeft() {
        return view.getPaddingLeft();
    }

    /**
     * 置上内边距
     *
     * @param val 值
     */
    public void paddingTop(int val) {
        view.setPadding(view.getPaddingTop(), val, view.getPaddingRight(), view.getPaddingBottom());
    }

    /**
     * 取上内边距
     */
    public int paddingTop() {
        return view.getPaddingTop();
    }

    /**
     * 置右内边距
     *
     * @param val 值
     */
    public void paddingRight(int val) {
        view.setPadding(view.getPaddingTop(), view.getPaddingTop(), val, view.getPaddingBottom());
    }

    /**
     * 取右内边距
     */
    public int paddingRight() {
        return view.getPaddingRight();
    }

    /**
     * 置下内边距
     *
     * @param val 值
     */
    public void paddingBottom(int val) {
        view.setPadding(view.getPaddingTop(), view.getPaddingTop(), view.getPaddingRight(), val);
    }

    /**
     * 取下内边距
     */
    public int paddingBottom() {
        return view.getPaddingBottom();
    }

    private ViewGroup.MarginLayoutParams getLp() {
        ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        if (layoutParams == null) layoutParams =
                new ViewGroup.MarginLayoutParams(view.getWidth(), view.getHeight());
        return layoutParams;
    }

    /**
     * 置外边距
     *
     * @param left   左外边距
     * @param top    上外边距
     * @param right  右外边距
     * @param bottom 下外边距
     */
    public void margin(int left, int top, int right, int bottom) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.leftMargin = left;
        layoutParams.topMargin = top;
        layoutParams.rightMargin = right;
        layoutParams.bottomMargin = bottom;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 置水平方向的外边距
     *
     * @param left  左外边距
     * @param right 右外边距
     */
    public void marginX(int left, int right) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.leftMargin = left;
        layoutParams.rightMargin = right;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 置垂直方向的外边距
     *
     * @param top    上外边距
     * @param bottom 下外边距
     */
    public void marginY(int top, int bottom) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.topMargin = top;
        layoutParams.bottomMargin = bottom;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 置左外边距
     *
     * @param val 值
     */
    public void marginLeft(int val) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.leftMargin = val;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 取左外边距
     */
    public int marginLeft() {
        return getLp().leftMargin;
    }

    /**
     * 置上外边距
     *
     * @param val 值
     */
    public void marginTop(int val) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.topMargin = val;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 取上外边距
     */
    public int marginTop() {
        return getLp().topMargin;
    }

    /**
     * 置右外边距
     *
     * @param val 值
     */
    public void marginRight(int val) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.rightMargin = val;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 取右外边距
     */
    public int marginRight() {
        return getLp().rightMargin;
    }

    /**
     * 置下外边距
     *
     * @param val 值
     */
    public void marginBottom(int val) {
        ViewGroup.MarginLayoutParams layoutParams = getLp();
        layoutParams.bottomMargin = val;
        view.setLayoutParams(layoutParams);
    }

    /**
     * 取下外边距
     */
    public int marginBottom() {
        return getLp().bottomMargin;
    }

    /**
     * 置可视状态
     *
     * @param v 可视状态，GONE: 消失不占位；INVISIBLE: 隐藏; VISIBLE: 可视
     */
    public void visibility(int v) {
        view.setVisibility(v);
    }

    /**
     * 取可视状态
     *
     * @return GONE: 消失不占位；INVISIBLE: 隐藏; VISIBLE: 可视
     */
    public int visibility() {
        return view.getVisibility();
    }


    /**
     * 关闭硬件加速
     */
    public void closeHardwareAcceleration() {
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    /**
     * 从父布局中删除自己
     */
    public void removeSelf() {
        ViewGroup v = (ViewGroup) view.getParent();
        if (v != null) v.removeView(view);
    }

    /**
     * 显示到顶层
     */
    public void toTop() {
        view.bringToFront();
    }

    /**
     * 取上下文
     */
    public Context getViewContext() {
        return view.getContext();
    }

    /**
     * 取id
     */
    public int getViewId() {
        return view.getId();
    }

    /**
     * 置视图id，需要android api 17才能使用
     */
    public int setViewId() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
            return 0;
        int id = View.generateViewId();
        view.setId(id);
        return id;
    }

    /**
     * 取类的名称
     */
    public String getClassSimpleName() {
        return view.getParent().getClass().getSimpleName();
    }

    /**
     * 取父布局对象
     */
    public ViewParent getParentView() {
        return view.getParent();
    }

    /**
     * 取父布局id
     */
    public int getParentId() {
        View v = (View) view.getParent();
        if (v == null) return -1;
        return v.getId();
    }

    /**
     * 置启用状态
     *
     * @param enabled 是否启用
     */
    public void setEnabled(boolean enabled) {
        view.setEnabled(enabled);
    }

    /**
     * 获取焦点
     */
    public void focus() {
        view.requestFocus();
    }

    /**
     * 取消焦点
     */
    public void blur() {
        view.clearFocus();
    }

    /**
     * 置可否单击，默认为 false，若为 false，将无法产生click事件，onTouch事件中也无法触发弹起事件: ACTION_UP
     * 调用 setOnClick 函数后，自动置为 true
     *
     * @param enable 可否
     */
    public void clickable(boolean enable) {
        view.setClickable(enable);
    }

    /**
     * 置可否触发长按事件，默认为 false，若为false，无法触发longClick事件
     * 调用 setOnLongClick 函数后，自动置为 true
     *
     * @param enable 可否
     */
    public void longClickable(boolean enable) {
        view.setLongClickable(enable);
    }

    /**
     * 置可获取焦点，使得组件在非触屏设备上拥有获取焦点的能力。
     *
     * @param enable 是否获取
     */
    public void focusable(boolean enable) {
        view.setFocusable(enable);
    }

    /**
     * 置可获取触摸屏模式的焦点，使得组件在触屏模式下获取焦点的能力
     *
     * @param enable 是否获取
     */
    public void focusableInTouchMode(boolean enable) {
        view.setFocusableInTouchMode(enable);
    }

    private void recycleBackgroundBitmap() {
        if (mBackgroundBitmap == null || mBackgroundBitmap.isRecycled()) return;
        mBackgroundBitmap.recycle();
        mBackgroundBitmap = null;
    }

    public void drawBackgroundDrawable() {
        if(mRippleEffect && setRippleEffect()) return;
        ViewDrawable drawable = new ViewDrawable(view);
        drawable.setBackgroundColor(mBackgroundColor);
        drawable.setLinearGradient(bgLinearGradient);
        drawable.setRadialGradient(bgRadialGradient);
        drawable.setBorderWidth(mBorderWidth);
        drawable.setBorderColor(mBorderColor);
        drawable.setBorderType(mBorderType);
        drawable.setBackground(mBackgroundBitmap);
        drawable.setShadow(mShadowRadius, mShadowDx, mShadowDy, mShadowColor);
        if (mCornerRadii != null) {
            drawable.setRadius(mCornerRadii[0], mCornerRadii[2], mCornerRadii[4], mCornerRadii[6]);
        }
        view.setBackground(drawable);

    }

    /**
     * 置水波纹特效，注意设置该特效后，组件的其他圆角、阴影，边框等效果均失效
     */
    private boolean setRippleEffect() {
        this.focusable(true);
        this.clickable(true);
        Resources.Theme theme = view.getContext().getTheme();
        TypedValue typedValue = new TypedValue();
        theme.resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true);
        int[] attribute = new int[]{android.R.attr.selectableItemBackground};
        try {
            TypedArray ta = theme.obtainStyledAttributes(typedValue.resourceId, attribute);
            view.setBackground(ta.getDrawable(0));
            ta.recycle();
            return true;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 设置背景颜色
     *
     * @param color 颜色
     */
    public void backgroundColor(int color) {
        mBackgroundColor = color;
        drawBackgroundDrawable();
    }

    /**
     * 取背景颜色
     */
    public int backgroundColor() {
        return mBackgroundColor;
    }

    /**
     * 设置线性渐变背景
     * @param x0 起点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图水平靠左的位置。
     * @param y0 起点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图垂直靠上的位置。
     * @param x1 终点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图水平靠右的位置。
     * @param y1 终点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图垂直靠下的位置。
     * @param colors 颜色数组，不同位置的颜色值
     * @param positions 位置数组，指定各个颜色的位置。设置的值范围时0-1，0表示起始位置, 1表示结束位置
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    public void setBackgroundLinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, int mode) {
        bgLinearGradient = new BgLinearGradient(x0, y0, x1, y1, colors, positions, mode);
        drawBackgroundDrawable();
    }

    /**
     * 设置线性渐变背景
     * @param x0 起点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图水平靠左的位置。
     * @param y0 起点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为0，表示在视图垂直靠上的位置。
     * @param x1 终点横坐标。0-1表示按视图宽度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图水平靠右的位置。
     * @param y1 终点纵坐标。0-1表示按视图高度比例计算，大于1和小于等于0表示固定的像素值。默认值为1，表示在视图垂直靠下的位置。
     * @param color1 开始的颜色值
     * @param color2 结束的颜色值
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    public void setBackgroundLinearGradient(float x0, float y0, float x1, float y1, int color1, int color2, int mode) {
        bgLinearGradient = new BgLinearGradient(x0, y0, x1, y1, color1, color2, mode);
        drawBackgroundDrawable();
    }

    /**
     *
     * @param centerX 中心点横坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图水平方向的中间位置。
     * @param centerY 中心点纵坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图垂直方向的中间位置。
     * @param radius 环形的半径，小于0时表示按视图宽度或高度的比例计算。
     *               大于等于0表示固定的像素值；
     *               -1 <= radius < 0 时，表示按短边的比例计算；
     *               -2 <= radius < -1 时，表示按长边的比例计算。
     *               -3 <= radius < -2 时，表示按视图宽度的比例计算。
     *               -4 <= radius < -3 时，表示按视图高度的比例计算。
     *               默认值为-1，即半径为视图最短边的长度。
     * @param colors 颜色数组，不同位置的颜色值
     * @param stops 位置数组，指定各个颜色的位置。设置的值范围时0-1，0表示起始位置, 1表示结束位置
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    public void setBackgroundRadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, int mode) {
        bgRadialGradient = new BgRadialGradient(centerX, centerY, radius, colors, stops, mode);
        drawBackgroundDrawable();
    }

    /**
     *
     * @param centerX 中心点横坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图水平方向的中间位置。
     * @param centerY 中心点纵坐标，0-1表示百分比，大于1和小于等于0表示固定的像素值。默认值为0.5f，表示在视图垂直方向的中间位置。
     * @param radius 环形的半径，小于0时表示按视图宽度或高度的比例计算。
     *               大于等于0表示固定的像素值；
     *               -1 <= radius < 0 时，表示按短边的比例计算；
     *               -2 <= radius < -1 时，表示按长边的比例计算。
     *               -3 <= radius < -2 时，表示按视图宽度的比例计算。
     *               -4 <= radius < -3 时，表示按视图高度的比例计算。
     *               默认值为-1，即半径为视图最短边的长度。
     * @param centerColor 中心点颜色
     * @param edgeColor 边缘颜色
     * @param mode 平铺方式，参考"TileMode"类的常量
     */
    public void setBackgroundRadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, int mode) {
        bgRadialGradient = new BgRadialGradient(centerX, centerY, radius, centerColor, edgeColor, mode);
        drawBackgroundDrawable();
    }

    /**
     * 同时设置视图的四个角的圆角大小
     *
     * @param radius 圆角大小
     */
    public void corner(int radius) {
        mCornerRadii = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
        drawBackgroundDrawable();
    }

    /**
     * 分别设置视图四个角的圆角大小
     *
     * @param topLeft     左上角
     * @param topRight    右上角
     * @param bottomRight 右下角
     * @param bottomLeft  左下角
     */
    public void corner(float topLeft, float topRight, float bottomRight, float bottomLeft) {
        mCornerRadii = new float[]{topLeft, topLeft, topRight, topRight, bottomRight, bottomRight, bottomLeft, bottomLeft};
        drawBackgroundDrawable();
    }

    /**
     * 视图有四个角，每个角有x和y两个方向的圆角大小，共8个圆角值
     *
     * @param topLeftX     左上角x方向的圆角大小
     * @param topLeftY     左上角y方向的圆角大小
     * @param topRightX    右上角x方向的圆角大小
     * @param topRightY    右上角y方向的圆角大小
     * @param bottomRightX 右下角x方向的圆角大小
     * @param bottomRightY 右下角y方向的圆角大小
     * @param bottomLeftX  左下角x方向的圆角大小
     * @param bottomLeftY  左下角y方向的圆角大小
     */
    public void corner(float topLeftX, float topLeftY, float topRightX, float topRightY,
                       float bottomRightX, float bottomRightY, float bottomLeftX, float bottomLeftY) {
        mCornerRadii = new float[]{topLeftX, topLeftY, topRightX, topRightY, bottomRightX, bottomRightY, bottomLeftX, bottomLeftY};
        drawBackgroundDrawable();
    }

    /**
     * 置边框宽度
     *
     * @param w 宽度
     */
    public void borderWidth(int w) {
        mBorderWidth = w;
        drawBackgroundDrawable();
    }

    /**
     * 取边框宽度
     */
    public int borderWidth() {
        return mBorderWidth;
    }

    /**
     * 置边框颜色
     *
     * @param color 颜色
     */
    public void borderColor(int color) {
        mBorderColor = color;
        drawBackgroundDrawable();
    }

    /**
     * 取边框颜色
     */
    public int borderColor() {
        return mBorderWidth;
    }

    /**
     * 取背景图片的位图数据
     */
    public Bitmap getBackgroundBitmap() {
        return mBackgroundBitmap;
    }

    /**
     * 置背景图片
     *
     * @param resId 图片资源id
     */
    public void background(int resId) {
        mBackgroundBitmap = BitmapUtils.fromResource(view.getContext(), resId);
        drawBackgroundDrawable();
    }

    /**
     * 置背景图片
     *
     * @param bitmap 图片位图数据
     */
    public void background(Bitmap bitmap) {
        mBackgroundBitmap = bitmap;
        drawBackgroundDrawable();
    }

    /**
     * 置背景图片，注意需要先申请读取文件的权限(READ_EXTERNAL_STORAGE)
     *
     * @param filePath 图片文件地址
     */
    public void background(String filePath) {
        mBackgroundBitmap = BitmapUtils.fromFile(filePath);
        drawBackgroundDrawable();
    }

    /**
     * 置背景图片
     *
     * @param bytes 字节数组
     */
    public void background(byte[] bytes) {
        mBackgroundBitmap = BitmapUtils.fromBytes(bytes);
        drawBackgroundDrawable();
    }

    private LonView.VisibilityChangeCallback mVisibilityChangeCallback;
    private LonView.FocusChangeCallback mFocusChangeCallback;
    private LonView.SizeChangeCallback mSizeChangeCallback;
    private LonView.LifeCallback mLifeCallback;

    /**
     * 置视图可视状态改变的事件回调
     *
     * @param event 回调的接口事件
     */
    public void setOnVisibilityChange(LonView.VisibilityChangeCallback event) {
        mVisibilityChangeCallback = event;
    }

    public void callVisibilityChangeCallback(@NonNull View v, int visibility) {
        if (mVisibilityChangeCallback != null)
            mVisibilityChangeCallback.onVisibilityChange(v, visibility);
    }

    /**
     * 置视图焦点改变的事件回调
     *
     * @param event 回调的接口事件
     */
    public void setOnFocusChange(LonView.FocusChangeCallback event) {
        mFocusChangeCallback = event;
    }

    public void callFocusChangeCallback(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
        if (mFocusChangeCallback != null)
            mFocusChangeCallback.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }

    /**
     * 置视图尺寸被改变的事件回调
     *
     * @param event 回调的接口事件
     */
    public void setOnSizeChange(LonView.SizeChangeCallback event) {
        mSizeChangeCallback = event;
    }

    public void callSizeChangeCallback(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        if (mSizeChangeCallback != null)
            mSizeChangeCallback.onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
    }

    /**
     * 置视图生命周期改变的事件回调
     *
     * @param event 回调的接口事件
     */
    public void setOnLiftChange(LonView.LifeCallback event) {
        mLifeCallback = event;
    }

    public void callViewCreate() {
        if (mLifeCallback != null) mLifeCallback.onCreate();
    }

    public void callViewDestroy() {
        if (mLifeCallback != null) mLifeCallback.onDestroy();
    }

    private float pressStartX = 0;
    private float pressStartY = 0;
    private static final int TOUCH_SLOP = 20;//移动阀值,移动距离超过这个值，才算开始移动,否则仍继续计算是否触发长按。
    private boolean isMove;

    /**
     * 置被单击的回调事件
     *
     * @param event 回调的接口事件
     */
    public void setOnClick(LonView.ClickCallback event) {
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (event != null) event.onClick(v);
            }
        });
    }

    /**
     * 置被长按的回调
     *
     * @param event 回调的接口事件
     */
    public void setOnLongClick(LonView.ClickCallback event) {
        view.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (event != null) return event.onLongClick(v);
                return false;
            }
        });
    }

    /**
     * 置触摸回调
     *
     * @param touchCallback 回调事件
     */
    public void setOnTouch(LonView.TouchCallback touchCallback) {
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                LonView.TouchMotion touchMotion = new LonView.TouchMotion(event);
                float x = event.getX();
                float y = event.getY();
                int action = event.getAction();
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        isMove = false;
                        pressStartX = x;
                        pressStartY = y;
                        if (touchCallback != null) touchCallback.onTouchDown(v, touchMotion);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (isMove) {
                            if (touchCallback != null)
                                touchCallback.onSlide(v, touchMotion, pressStartX, pressStartY, x, y);
                            break;
                        } else if (Math.abs(pressStartX - x) > TOUCH_SLOP ||
                                Math.abs(pressStartY - y) > TOUCH_SLOP) {
                            //移动超过了阈值，表示移动了
                            isMove = true;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (touchCallback != null) touchCallback.onTouchUp(v, touchMotion);
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        if (touchCallback != null) touchCallback.onTouchCancel(v, touchMotion);
                        break;
                }

                //多点触控部分
                if (touchCallback != null) {
                    touchCallback.onMultiTouch(v, touchMotion);
                    return touchCallback.intercept(v, touchMotion);
                }

                return false;
            }
        });
    }

    /******************取布局属性的值************************/

    public Integer getAttrValueLayoutWidth() {
        return mLayoutWidth;
    }

    public Integer getAttrValueLayoutHeight() {
        return mLayoutHeight;
    }

    public Integer getAttrValuePadding() {
        return mPadding;
    }

    public Integer getAttrValuePaddingLeft() {
        return mPaddingLeft;
    }

    public Integer getAttrValuePaddingTop() {
        return mPaddingTop;
    }

    public Integer getAttrValuePaddingRight() {
        return mPaddingRight;
    }

    public Integer getAttrValuePaddingBottom() {
        return mPaddingBottom;
    }

    public Integer getAttrValueLayoutMargin() {
        return mLayoutMargin;
    }

    public Integer getAttrValueLayoutMarginLeft() {
        return mLayoutMarginLeft;
    }

    public Integer getAttrValueLayoutMarginRight() {
        return mLayoutMarginRight;
    }

    public Integer getAttrValueLayoutMarginTop() {
        return mLayoutMarginTop;
    }

    public Integer getAttrValueLayoutMarginBottom() {
        return mLayoutMarginBottom;
    }

    public void setBackgroundBitmap(Bitmap mBackgroundBitmap) {
        this.mBackgroundBitmap = mBackgroundBitmap;
    }

    public int getBackgroundColor() {
        return mBackgroundColor;
    }

    public void setBackgroundColor(int mBackgroundColor) {
        this.mBackgroundColor = mBackgroundColor;
    }

    public int getBorderWidth() {
        return mBorderWidth;
    }

    public void setBorderWidth(int mBorderWidth) {
        this.mBorderWidth = mBorderWidth;
    }

    public int getBorderColor() {
        return mBorderColor;
    }

    public void setBorderColor(int mBorderColor) {
        this.mBorderColor = mBorderColor;
    }

    public int getBorderType() {
        return mBorderType;
    }

    public void setBorderType(int mBorderType) {
        this.mBorderType = mBorderType;
    }

    public float[] getCornerRadii() {
        return mCornerRadii;
    }

    public void setCornerRadii(float[] mCornerRadii) {
        this.mCornerRadii = mCornerRadii;
    }

    public float getShadowRadius() {
        return mShadowRadius;
    }

    public void setShadowRadius(float mShadowRadius) {
        this.mShadowRadius = mShadowRadius;
    }

    public float getShadowDx() {
        return mShadowDx;
    }

    public void setShadowDx(float mShadowDx) {
        this.mShadowDx = mShadowDx;
    }

    public float getShadowDy() {
        return mShadowDy;
    }

    public void setShadowDy(float mShadowDy) {
        this.mShadowDy = mShadowDy;
    }

    public int getShadowColor() {
        return mShadowColor;
    }

    public void setShadowColor(int mShadowColor) {
        this.mShadowColor = mShadowColor;
    }

    public float getLinearGradientX0() {
        return mLinearGradientX0;
    }

    public float getLinearGradientY0() {
        return mLinearGradientY0;
    }

    public float getLinearGradientX1() {
        return mLinearGradientX1;
    }

    public float getLinearGradientY1() {
        return mLinearGradientY1;
    }

    public int getLinearGradientMode() {
        return mLinearGradientMode;
    }

    public Integer getLinearGradientColorStart() {
        return mLinearGradientColorStart;
    }

    public Integer getLinearGradientColorEnd() {
        return mLinearGradientColorEnd;
    }

    public float getRadialGradientCenterX() {
        return mRadialGradientCenterX;
    }

    public float getRadialGradientCenterY() {
        return mRadialGradientCenterY;
    }

    public float getRadialGradientRadius() {
        return mRadialGradientRadius;
    }

    public int getRadialGradientMode() {
        return mRadialGradientMode;
    }

    public Integer getRadialGradientColorCenter() {
        return mRadialGradientColorCenter;
    }

    public Integer getRadialGradientColorEdge() {
        return mRadialGradientColorEdge;
    }

    public BgLinearGradient getBgLinearGradient() {
        return bgLinearGradient;
    }

    public BgRadialGradient getBgRadialGradient() {
        return bgRadialGradient;
    }

    public int[] getLinearGradientColors() {
        return mLinearGradientColors;
    }

    public float[] getLinearGradientPositions() {
        return mLinearGradientPositions;
    }

    public int[] getRadialGradientColors() {
        return mRadialGradientColors;
    }

    public float[] getRadialGradientPositions() {
        return mRadialGradientPositions;
    }

    public boolean getRippleEffectStatus() {
        return mRippleEffect;
    }

    public void setRippleEffectEnable(boolean enable) {
        boolean isChange = this.mRippleEffect != enable;
        this.mRippleEffect = enable;
        if(isChange) drawBackgroundDrawable();
    }
}
